package com.yu.transport.handler;

import com.yu.loader.ExtensionLoader;
import com.yu.serialize.Serializer;
import com.yu.transfer.RpcMessage;
import com.yu.transport.constants.NettyConstants;
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.MessageToByteEncoder;
import lombok.extern.slf4j.Slf4j;

import java.util.concurrent.atomic.AtomicInteger;

/**
 * @PackageName: com.yu.transport.codec
 * @Description:
 * @Version: v1.0.0
 * @Author: yuweilin
 * @Date: 15:05
 * <p>
 * Modification History:
 * Date         Author          Version            Description
 * ------------------------------------------------------------
 * 2021/1/28      yuweilin         v1.0.0               新建
 */
@Slf4j
public class RpcMessageEncoder extends MessageToByteEncoder<RpcMessage> {
    private static final AtomicInteger ATOMIC_INTEGER = new AtomicInteger(0);

    @Override
    protected void encode(ChannelHandlerContext ctx, RpcMessage msg, ByteBuf out) throws Exception {
        try {
            out.writeBytes(NettyConstants.MAGIC_NUMBER);
            out.writeByte(NettyConstants.VERSION);
            //先预留一个写长度的空间
            out.writerIndex(out.writerIndex()+4);
            byte messageType = msg.getMessageType();
            out.writeByte(messageType);
            out.writeInt(ATOMIC_INTEGER.getAndIncrement());
            byte[] bodyBytes = null;
            int fullLength = NettyConstants.HEAD_LENGTH;
            if (messageType!=NettyConstants.HEARTBEAT_TYPE){
                Serializer serializer = ExtensionLoader.getExtensionLoader(Serializer.class).getExtension("protostuff");
                bodyBytes = serializer.serialize(msg.getData());
                fullLength += bodyBytes.length;
            }

            if (bodyBytes!=null){
                out.writeBytes(bodyBytes);
            }
            int writeIndex = out.writerIndex();
            out.writerIndex(writeIndex-fullLength+NettyConstants.MAGIC_NUMBER.length+1);
            out.writeInt(fullLength);
            out.writerIndex(writeIndex);
        }catch (Exception e){
            log.error("编码失败",e);
        }
    }
}
